package classpath

import (
	"archive/zip"
	"errors"
	"io/ioutil"
	"path/filepath"
)

// 从压缩包或jar包中查找
type ZipEntry struct {
	absPath string
}

func newZipEntry(path string) *ZipEntry {
	// Abs函数返回path代表的绝对路径，如果path不是绝对路径，会加入当前工作目录以使之成为绝对路径。
	// 因为硬链接的存在，不能保证返回的绝对路径是唯一指向该地址的绝对路径。
	absPath, err := filepath.Abs(path)
	if err != nil {
		panic(err)
	}
	return &ZipEntry{absPath}
}

// 从压缩包或者jar包中查找class的二进制字节流
func (self *ZipEntry) ReadClass(classname string) ([]byte, Entry, error) {

	reader, err := zip.OpenReader(self.absPath)
	if err != nil {
		return nil, nil, err
	}

	defer reader.Close()

	for _, aFile := range reader.File {
		if aFile.Name == classname {
			// Open方法返回一个io.ReadCloser接口，提供读取文件内容的方法。可以同时读取多个文件。
			rc, err := aFile.Open()
			if err != nil {
				return nil, nil, err
			}
			defer rc.Close()
			// 读取
			data, err := ioutil.ReadAll(rc)
			if err != nil {
				return nil, nil, err
			}
			return data, self, nil

		}
	}
	return nil, nil, errors.New("class not found " + classname)
}

// 返回此ZipEntry的字符串表示
func (self *ZipEntry) String() string {
	return self.absPath
}
